// 值多态
#include<variant>
#include <iostream>
using namespace std;

constexpr double pi = 3.14;
 
struct Circle 
{ 
    double r; 
};

double getArea(const Circle& c) 
{
    return pi * c.r * c.r;
}

double getPerimeter(const Circle& c) 
{
    return 2 * pi * c.r;
}

 
struct Rectangle 
{ 
    double w; double h; 
};

double getArea(const Rectangle& c) 
{
    return c.h * c.w;
}

double getPerimeter(const Rectangle& c) {
    return 2 * (c.h + c.w);
}

struct Square{double len;};
double getArea(const Square& c) {
    return c.len * c.len;
}

double getPerimeter(const Square& c) {
    return 2 * (c.len + c.len);
}

 
using Shape = std::variant<Circle, Rectangle, Square>;
double getArea(const Shape& c) {
    return std::visit([](const auto& data) {return getArea(data); }, c);
}

double getPerimeter(const Shape& c) {
    return std::visit([](const auto& data) {return getPerimeter(data); }, c);
}

int main() {
    Shape sp = Circle{2};
    std::cout<<getArea(sp);
 
    sp = Rectangle{2, 3};
    std::cout << getArea(sp);

    sp = Square{5};
    cout << getArea(sp);
    cout << getPerimeter(sp);
}